package com.zzh.lib.views;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.zzh.lib.views.listener.HDragViewCallback;

import androidx.annotation.NonNull;
import androidx.customview.widget.ViewDragHelper;

/**
 * Created by ZZH on 2022/2/18.
 *
 * @Date: 2022/2/18
 * @Email: zzh_hz@126.com
 * @QQ: 1299234582
 * @Author: zzh
 * @Description: 可拖拽控件，子控件可以拖拽
 */
public class HDragViewLayout extends FrameLayout {
    public static final String tag = "HDragViewLayout";
    private boolean debug = false;

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    /**
     * 滑动滑块
     */
    private View mLockBtn;
    /**
     * 拽托帮助类
     */
    private ViewDragHelper mViewDragHelper;

    HDragViewCallback mHDragViewCallback;

    public HDragViewCallback getDragViewCallback() {
        return mHDragViewCallback;
    }

    public HDragViewLayout setDragViewCallback(HDragViewCallback HDragViewCallback) {
        mHDragViewCallback = HDragViewCallback;
        return this;
    }

    public HDragViewLayout(Context context) {
        this(context, null);
    }

    public HDragViewLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HDragViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {

        final HDragViewLayout slideRail = this;
        mViewDragHelper = ViewDragHelper.create(this, 0.3f, new ViewDragHelper.Callback() {

            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                //判断能拽托的View，这里会遍历内部子控件来决定是否可以拽托，我们只需要滑块可以滑动
                return child == mLockBtn;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                //拽托子View横向滑动时回调，回调的left，则是可以滑动的左上角x坐标
                int lockBtnWidth = mLockBtn.getWidth();
                //限制左右临界点
                int fullWidth = slideRail.getWidth();
                //最少的左边
                int leftMinDistance = getPaddingStart();
                //最多的右边
                int leftMaxDistance = fullWidth - getPaddingEnd() - lockBtnWidth;
                //修复两端的临界值
                if (left < leftMinDistance) {
                    return leftMinDistance;
                } else if (left > leftMaxDistance) {
                    return leftMaxDistance;
                }
                return left;
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                //拽托子View纵向滑动时回调，锁定顶部padding距离即可，不能不复写，否则少了顶部的padding，位置就偏去上面了
                int lockBtnHeight = mLockBtn.getHeight();
                int fullHeight = slideRail.getHeight();
                int topMinDistance = getPaddingTop();
                int topMaxDistance = fullHeight - getPaddingBottom() - lockBtnHeight;
                if (top < topMinDistance) {
                    return topMinDistance;
                } else if (top > topMaxDistance) {
                    return topMaxDistance;
                }
                return top;
            }

            @Override
            public void onViewCaptured(View capturedChild, int activePointerId) {
                super.onViewCaptured(capturedChild, activePointerId);
                //捕获到拽托的View时回调，获取顶部距离
                if (debug) {
                    Log.d(tag, "onViewCaptured, activePointerId: " + activePointerId);
                }
                if (mHDragViewCallback != null) {
                    mHDragViewCallback.onViewCaptured(capturedChild, activePointerId);
                }
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                if (debug)
                    Log.d(tag, "onViewReleased, xvel: " + xvel + ", yvel: " + yvel);
                if (mHDragViewCallback != null) {
                    mHDragViewCallback.onViewReleased(releasedChild, xvel, yvel);
                }
            }

            @Override
            public void onViewDragStateChanged(int state) {
                super.onViewDragStateChanged(state);
                if (debug) Log.d(tag, "onViewDragStateChanged, state: " + state);
            }

            @Override
            public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                if (debug) Log.d(tag, "onViewPositionChanged: " + left + ", " + top + ", " + dx + ", " + dy);
                if (mHDragViewCallback != null) {
                    mHDragViewCallback.onViewPositionChanged(changedView, left, top, dx, dy);
                }
            }

            @Override
            public void onEdgeTouched(int edgeFlags, int pointerId) {
                super.onEdgeTouched(edgeFlags, pointerId);
                if (debug) Log.d(tag, "onEdgeTouched: edgeFlags: " + edgeFlags + ", pointerId: " + pointerId);
            }

            @Override
            public boolean onEdgeLock(int edgeFlags) {
                if (debug) Log.d(tag, "onEdgeLock: edgeFlags: " + edgeFlags);
                return super.onEdgeLock(edgeFlags);
            }

            @Override
            public void onEdgeDragStarted(int edgeFlags, int pointerId) {
                super.onEdgeDragStarted(edgeFlags, pointerId);
                if (debug) Log.d(tag, "onEdgeDragStarted: edgeFlags: " + edgeFlags + ", pointerId: " + pointerId);
            }

            @Override
            public int getOrderedChildIndex(int index) {
                if (debug) Log.d(tag, "getOrderedChildIndex: index: " + index);
                return super.getOrderedChildIndex(index);
            }

            @Override
            public int getViewHorizontalDragRange(@NonNull View child) {
                if (debug) Log.d(tag, "getViewHorizontalDragRange:  ");
                return super.getViewHorizontalDragRange(child);
            }

            @Override
            public int getViewVerticalDragRange(@NonNull View child) {
                if (debug) Log.d(tag, "getViewVerticalDragRange:  ");
                return super.getViewVerticalDragRange(child);
            }
        });
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //找到需要拽托的滑块
        mLockBtn = findViewById(R.id.h_drag_view);
        if (mLockBtn == null) {
            throw new NullPointerException("必须要有一个滑动滑块");
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //将onInterceptTouchEvent委托给ViewDragHelper
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //将onTouchEvent委托给ViewDragHelper
        mViewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        //判断是否移动到头了，未到头则继续
        if (mViewDragHelper != null) {
            if (mViewDragHelper.continueSettling(true)) {
                invalidate();
            }
        }
    }
}
